package cn.xy.commons.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.Code128Writer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;

import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;

/**
 * 条形码生成工具
 *
 *  @author xy
 * @date 2023-04-06
 */
@Slf4j
public class BarcodeUtil {

    private BarcodeUtil() {
        throw new IllegalStateException("Utility class");
    }

    private static final int WIDTH = 200;

    private static final int HEIGHT = 120;

    private static final int BLACK = 0xFF000000;

    private static final int WHITE = 0xFFFFFFFF;

    private static final Map<EncodeHintType, Object> HASH_MAP = new HashMap<>();

    static {
        HASH_MAP.put(EncodeHintType.CHARACTER_SET, "utf-8");
        HASH_MAP.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        HASH_MAP.put(EncodeHintType.MARGIN, 2);
    }

    /**
     * 生成条形码
     *
     * @param content  content
     * @param width    width
     * @param height   height
     * @param hintsMap hintsMap
     * @return BufferedImage
     */
    public static BufferedImage generateBarcode(String content, int width, int height, Map<EncodeHintType, Object> hintsMap) {
        Code128Writer writer = new Code128Writer();
        BufferedImage barcode = null;
        try {
            BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.CODE_128, width, height, hintsMap);
            barcode = BarcodeUtil.toBufferedImage(bitMatrix);
        } catch (WriterException e) {
            log.error("barcode generate error: ", e);
        }
        return barcode;
    }

    private static BufferedImage toBufferedImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, (matrix.get(x, y) ? BLACK : WHITE));
            }
        }
        return image;
    }

    /**
     * 生成条形码
     *
     * @param content content
     * @return BufferedImage
     */
    public static BufferedImage generateBarcode(String content) {
        return BarcodeUtil.generateBarcode(content, WIDTH, HEIGHT, HASH_MAP);
    }

    /**
     * 生成条形码
     *
     * @param content content
     * @param width   width
     * @param height  height
     * @return BufferedImage
     */
    public static BufferedImage generateBarcode(String content, int width, int height) {
        return BarcodeUtil.generateBarcode(content, width, height, HASH_MAP);
    }

}
